package liquidfs.data.ops;

import java.io.*;
import java.util.*;

import liquidfs.*;
import liquidfs.core.*;
import liquidfs.data.*;
import liquidfs.data.ex.*;

public class QueryStorageDevicesOperation extends AbstractFileOperation<List<PeerDevice>> {
   
	public QueryStorageDevicesOperation(PeerDevice origin, String filepath) {
		super(origin, filepath);
	}

	@Override
	public List<PeerDevice> execute(Application app, InputStream in, OutputStream out) {
	   
	   // Get a reference to the file system
		LiquidFileSystem fs = app.getFileSystem();
		
		List<PeerDevice> devices = new ArrayList<PeerDevice>(1);
		
		// If the file is local, count it
		if (fs.isLocal(this.getFilePath())) {
		   devices.add(fs.getLocalDevice());
		}
		
		// Iterate through each device we're connected two, except the ones that have already been queried
		for (Link link : app.getConfiguration().getLinks()) {
		
		   // Skip devices that have already been queried
		   if (this.reached(link.getDevice())) {
		      continue;
		   }
		   
   		// Pass this message along to other links in the network
   		Result<List<PeerDevice>> result = fs.relay(link, this, null, null);
   		List<PeerDevice> remoteDevices;
   		
   		// Get the contents; if this device had nothing to add, skip it
   		try {
   		   remoteDevices = result.getData();
   		}
   		catch (AlreadyRespondedException e) {
   		   continue; // We already have those devices
   		}
   		catch (CommunicationException e) {
   		   continue; // We wont list those devices
   		}
   		
   		// Merge the local and remote lists
   		for (PeerDevice device : remoteDevices) {
   		   if (!devices.contains(device)) {
   		      devices.add(device);
   		   }
   		}
		}
		
		// Return the list we've compiled
		return devices;
		
	}

}
